local ActDefine = require("activity.Define")
--local Util = require("common.Util")
local ActivityExcel = require("excel.Activity")
local DailyActConfig = ActivityExcel.dailyAct
local ActRuleConfig = ActivityExcel.dailyActRule
local ActHandlerW = require("activity.HandlerW")
local InnerDataManagerFW = require("innerdata.InnerDataManagerFW")
local InnerDataDefine = require("innerdata.Define")
local Timer = require("core.Timer")
local PowerRankLogic = require("rank.PowerRankLogic")

DailyActList = DailyActList or {}
CallBackList = CallBackList or {}

---------------------------------
--每个活动的数据在DB中是以活动配置编号作为键进行保存的
---------------------------------

function onActCheck()
    local nDate = os.date("*t", os.time())
    local nWday = (nDate.wday + 5) % 7 + 1
    local nHour = nDate.hour
    local nMin = nDate.min
    --print("daily activity check ", nWday, " , ", nHour, ":", nMin)
    for nType, v in pairs(DailyActList) do
        if v._configList then
            for nActConfigID, nActList in pairs(v._configList) do
                local nActConfigData = DailyActConfig[nActConfigID]
                if not nActConfigData then
                    break
                end

                --检查有没有要预告的活动
                for nActNum, nActArgs in pairs(nActList) do
                    if not nActConfigData.dayWed[nWday] or nActConfigData.dayWed[nWday] == 0 then
                        nActArgs.show = 1 
                        local nActRule = ActRuleConfig[nActArgs.ruleid]
                        if nActRule and nActArgs.gmclose == 0 then
                            local nLeftMin = (nActArgs.hour * 60 + nActArgs.min) - (nHour * 60 + nMin)
                            if nLeftMin >= 0 and nLeftMin <= nActRule.beginbefore then
                                if not onProcessAct(nType, nActArgs._configID, nActNum, nLeftMin * 60, ActDefine.ACT_STATE_BEFORESTART, nActArgs) then
                                end
                            end
                        end
                    else
                        nActArgs.show = nil 
                    end
                end


                --检查预告中的活动
                if v._beginbefore then
                    if v._beginbefore.endtime <= os.time() then
                        local nActRule = ActRuleConfig[v._beginbefore.actArgs.ruleid]
                        if nActRule then
                            if not onProcessAct(nType, v._beginbefore.actArgs._configID, v._beginbefore.actnum, nActRule.gap * 60, ActDefine.ACT_STATE_RUNNING, v._beginbefore.actArgs) then
                            end
                        end
                    end
                end

                --检查进行中的活动
                if v._running then
                    if v._running.endtime <= os.time() then      --活动到达结束时间
                        --onEndAct(v._running.actnum)
                        onProcessAct(nType, v._running.actArgs._configID, v._running.actnum, 0, ActDefine.ACT_STATE_ENDED, v._running.actArgs)
                        v._running = nil
                    end
                end

                --检查结束与超时的活动
            end
        end
    end
end

function onProcessAct(actType, actConfigID, actNum, gap, actState, actArgs)
    local actTypeData = DailyActList[actType]
    if not actTypeData or not actNum or not gap or not actState then
        return false
    end

    if actState == ActDefine.ACT_STATE_READY then
        if not actTypeData._configList[actConfigID][actNum] then
            actTypeData._configList[actConfigID][actNum] = actArgs
            ActHandlerW.onSend2ClientDailyActUpdate(actNum, 1, actArgs)
            return true
        end
    elseif actState == ActDefine.ACT_STATE_BEFORESTART then
        if not onCheckActIsBeginBefore(actType) and not onCheckActIsRunning(actType) then
            actTypeData._beginbefore = {starttime = os.time(), endtime = os.time() + gap, actnum = actNum, actArgs = actArgs}
            onCallBack(actType, actNum, actState, actArgs)
            ActHandlerW.onSendBroadcast(actType, actState, actArgs)
            ActHandlerW.onSend2ClientDailyActUpdate(actNum, 2, actArgs)
            return true
        elseif onCheckActIsRunning(actType) then
            if actTypeData._running.actnum ~= actNum then
                ActHandlerW.onSend2ClientDailyActUpdate(actNum, 2, actArgs)
            end
            --else
            --    ActHandlerW.onSend2ClientDailyActUpdate(actNum, 2, actArgs)
        end
    elseif actState == ActDefine.ACT_STATE_RUNNING then
        if not onCheckActIsRunning(actType) then
            actTypeData._running = {starttime = os.time(), endtime = os.time() + gap, actnum = actNum, actArgs = actArgs}
            actTypeData._beginbefore = nil
            onCallBack(actType, actNum, actState, actArgs)
            onSend2LActUpdate(actType, actState, actArgs)
            ActHandlerW.onSendBroadcast(actType, actState, actArgs)
            ActHandlerW.onSend2ClientDailyActUpdate(actNum, 2, actArgs)
            return true
        else
            if not actTypeData._running or (actTypeData._running and actTypeData._running.actnum ~= actNum) then
                ActHandlerW.onSend2ClientDailyActUpdate(actNum, 2, actArgs)
            end
        end
    elseif actState == ActDefine.ACT_STATE_ENDED then
        if not actTypeData._endList[actConfigID] then
            actTypeData._endList[actConfigID] = {}
        end
        actTypeData._endList[actConfigID][actNum] = 1
        actTypeData._beginbefore = nil
        actTypeData._running = nil
        onCallBack(actType, actNum, actState, actArgs)
        ActHandlerW.onSend2ClientDailyActUpdate(actNum, 2, actArgs)
        onSend2LActUpdate(actType, actState, actArgs)
        ActHandlerW.onSendBroadcast(actType, actState, actArgs)
        return true
    end
    return false
end


function onAddAct(actConfigID, startHour, startMin, ruleID, status)
    local nActConfigData = DailyActConfig[actConfigID]
    if not nActConfigData then
        return
    end

    local nActRule = ActRuleConfig[ruleID]
    if not nActRule then
        return
    end

    local nDifTime = math.ceil(Timer.onGetDeviationTime("activitycheck", true) / 1000) --修正秒数误差

    local nStatus = tonumber(status)

    local nTempNum = actConfigID..startHour..startMin
    local nActArgs = {_configID = actConfigID, hour = tonumber(startHour), min = tonumber(startMin), ruleid = tonumber(ruleID), type = nActConfigData.actType, gmclose = 0}
    onProcessAct(nActConfigData.actType, actConfigID, nTempNum, 0, ActDefine.ACT_STATE_READY, nActArgs)

    if onCheckActIsBeginBefore(nActConfigData.actType) or onCheckActIsRunning(nActConfigData.actType) then
        return
    end

    if nStatus == 1 then         --添加到预告列表
        onProcessAct(nActConfigData.actType, actConfigID, nTempNum, nActRule.beginbefore * 60 - nDifTime, ActDefine.ACT_STATE_BEFORESTART, nActArgs)
    elseif nStatus == 2 then     --添加到进行中列表
        onProcessAct(nActConfigData.actType, actConfigID, nTempNum, nActRule.gap * 60 - nDifTime, ActDefine.ACT_STATE_RUNNING, nActArgs)
    end
    return true
    --Util.printTable(DailyActList)
end


function onEndAct(actConfigID)
    local nActConfigData = DailyActConfig[actConfigID]
    if not nActConfigData then
        return
    end

    local nActType = nActConfigData.actType
    if DailyActList[nActType] and (DailyActList[nActType]._beginbefore or DailyActList[nActType]._running) then
        local nActArgs = DailyActList[nActType]._beginbefore and DailyActList[nActType]._beginbefore.actArgs or DailyActList[nActType]._running.actArgs
        local nTempNum = actConfigID .. nActArgs.hour..nActArgs.min
        onProcessAct(nActType, actConfigID, nTempNum, 0, ActDefine.ACT_STATE_ENDED, nActArgs)
    end
end

function onGMCtlAct(actConfigID, actNum, gmStatic)
    local nActConfigData = DailyActConfig[actConfigID]
    if not nActConfigData then
        return false
    end

    local nActType = nActConfigData.actType
    if DailyActList[nActType] and DailyActList[nActType]._configList and DailyActList[nActType]._configList[actNum] then
        DailyActList[nActType]._configList[actNum].gmclose = gmStatic
    end
end

function onGetActStatus(actType, actNum, startHour, startMin)
    if DailyActList[actType]._beginbefore and DailyActList[actType]._beginbefore.actArgs.hour == startHour and DailyActList[actType]._beginbefore.actArgs.min == startMin then
        return ActDefine.ACT_STATE_BEFORESTART
    elseif DailyActList[actType]._running and DailyActList[actType]._running.actArgs.hour == startHour and DailyActList[actType]._running.actArgs.min == startMin and DailyActList[actType]._running._finish ~= true then
        return ActDefine.ACT_STATE_RUNNING
        --elseif DailyActList[actType]._endList and DailyActList[actType]._endList[actNum] and DailyActList[actType]._endList[actNum][startMin] then
        --    return ActDefine.ACT_STATE_ENDED
    elseif DailyActList[actType]._running and DailyActList[actType]._running.actnum == actNum and DailyActList[actType]._running._finish == true then
        return ActDefine.ACT_STATE_ENDED
    else
        local nDate = os.date("*t", os.time())
        local nHour = nDate.hour
        local nMin = nDate.min
        if onCheckIsEnd(startHour, nHour, startMin, nMin) then
            return ActDefine.ACT_STATE_ENDED
        else
            return ActDefine.ACT_STATE_READY
        end
    end
end

function onSetActFinish(actType, actArgs)
    if DailyActList[actType]._running then
        DailyActList[actType]._running._finish = true
        ActHandlerW.onSend2ClientDailyActUpdate(DailyActList[actType]._running.actnum, 2, actArgs)
    end
end

function onCheckIsEnd(startHour, nowHour, startMin, nowMin)
    if startHour == nowHour then
        return startMin <= nowMin
    else
        return startHour < nowHour
    end
end

function onGetLeftTime(actNum, actArgs)
    local nActConfigID = actArgs._configID
    local nActConfigData = DailyActConfig[nActConfigID]
    if nActConfigData then
        local nStatus = onGetActStatus(actArgs.type, actNum, actArgs.hour, actArgs.min)
        if nStatus == ActDefine.ACT_STATE_READY then
            local nDate = os.date("*t", os.time())
            local nHour = nDate.hour
            local nMin = nDate.min
            local nSec = nDate.sec
            return (actArgs.hour * 3600 + actArgs.min * 60) - (nHour * 3600 + nMin * 60 + nSec)
        elseif nStatus == ActDefine.ACT_STATE_BEFORESTART or nStatus == ActDefine.ACT_STATE_RUNNING then
            return DailyActList[actArgs.type]._beginbefore and (DailyActList[actArgs.type]._beginbefore.endtime - os.time()) or (DailyActList[actArgs.type]._running.endtime - os.time())
        else
            return 0
        end
    end
end

function onGetEndTime(actNum, actArgs)
    local nActConfigID = actArgs._configID
    local nActConfigData = DailyActConfig[nActConfigID]
    if nActConfigData then
        local nStatus = onGetActStatus(actArgs.type, actNum, actArgs.hour, actArgs.min)
        if nStatus == ActDefine.ACT_STATE_BEFORESTART or nStatus == ActDefine.ACT_STATE_RUNNING then
            return DailyActList[actArgs.type]._beginbefore and (DailyActList[actArgs.type]._beginbefore.endtime) or (DailyActList[actArgs.type]._running.endtime)
        else
            return 0
        end
    end
end

function onGetCurRunningActStartTime(actType)
    if DailyActList[actType]._running then
        return DailyActList[actType]._running.starttime
    end
    return 0
end

function onGetCurRunningActEndTime(actType)
    if DailyActList[actType]._running then
        return DailyActList[actType]._running.endtime
    end
    return 0
end

function onGetRunningActRuleID(actConfigID)
    local nActConfigData = DailyActConfig[actConfigID]
    if nActConfigData then
        local nActType = nActConfigData.actType
        if DailyActList[nActType]._running then
            return DailyActList[nActType]._running.actArgs.ruleid
        else
            return nil
        end
    end
end

function onGetActArgs(ruleID)
    local nActRule = ActRuleConfig[ruleID]
    if nActRule then
        return nActRule.args
    end
end

function onGetActCondition(ruleID)
    local nActRule = ActRuleConfig[ruleID]
    if nActRule then
        return nActRule.condition
    end
end

function onCheckActIsRunning(actType)
    if DailyActList[actType]._running then
        return true
    end
end

function onCheckActIsBeginBefore(actType)
    if DailyActList[actType]._beginbefore then
        return true
    end
end

function onDayCrossActUpdate()
    for k, v in pairs(DailyActConfig) do
        if v._endList then
            v._endList = {}
        end
    end
end

function onSend2LActUpdate(actType, status, actArgs)
    local nDateTime = os.date("*t")
    nDateTime.hour = actArgs.hour
    nDateTime.min = actArgs.min
    nDateTime.sec = 0
    --local nStartTime = os.time(nDateTime)
    local nStartTime = 0 
    local nEndTime = 0
    if status == ActDefine.ACT_STATE_BEFORESTART or status == ActDefine.ACT_STATE_RUNNING then
        nStartTime =DailyActList[actType]._beginbefore and (DailyActList[actType]._beginbefore.starttime) or (DailyActList[actType]._running.starttime) 
        nEndTime = DailyActList[actType]._beginbefore and (DailyActList[actType]._beginbefore.endtime) or (DailyActList[actType]._running.endtime)
    end
    local nSend2Ldata = {
        type = 1,
        data = {
            status = status,
            actType = actType,
            startTime = nStartTime,
        endTime = nEndTime,
        actArgs = actArgs,
        powerRank = (actType == ActDefine.ACT_TYPE_JZWAR_ACT) and PowerRankLogic.POWER_RANK or nil,
    }
}
InnerDataManagerFW.Send2LInnerData(nil, InnerDataDefine.INNERDATA_TYPE_ACT, nSend2Ldata)
end

function onCallBack(nActType, actNum, status, actArgs)
    local nCallBackData = CallBackList[nActType]
    if nCallBackData and nCallBackData[status] then
        nCallBackData[status](actNum, actArgs, nCallBackData.args)
    end
end

function onRegisterCallBack(nActType, onBeginBefore, onRunning, onEnd, actArgs)
    CallBackList[nActType] = {[ActDefine.ACT_STATE_BEFORESTART] = onBeginBefore, [ActDefine.ACT_STATE_RUNNING] = onRunning, [ActDefine.ACT_STATE_ENDED] = onEnd, args = actArgs}
end

initStatus = initStatus or false
function onInit(clear)
    if initStatus == false or clear then
        if clear then
            for nType, v in pairs(DailyActList) do
                for nActConfigID, nActData in pairs(v._configList) do
                    for nActNum, nActArgs in pairs(nActData) do
                        onProcessAct(nType, nActConfigID, nActNum, 0, ActDefine.ACT_STATE_ENDED, nActArgs)
                    end
                end
                DailyActList[nType] = nil
            end
        end

        for k, v in pairs(DailyActConfig) do
            if not DailyActList[v.actType] then
                DailyActList[v.actType] = {
                    _beginbefore = nil,             --预告中的活动
                    _running = nil,                 --运行中的活动
                    _endList = {},
                }
            end

            DailyActList[v.actType]._configList = DailyActList[v.actType]._configList or {}
            for nHour, nMinData in pairs(v.startTime) do
                for nMin, nArgs in pairs(nMinData) do
                    local actNum = k..nHour..nMin
                    if not DailyActList[v.actType]._configList[k] then
                        DailyActList[v.actType]._configList[k] = {}
                    end
                    DailyActList[v.actType]._configList[k][actNum] = {_configID = k, hour = nHour, min = nMin, ruleid = nArgs, type = v.actType, gmclose = 0, show = v.show}
                end
            end
        end
        initStatus = true
        --Util.printTable(DailyActList)
    end
end

onInit()
